﻿using AutoMapper;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Linq.Dynamic.Core;
using System.Reflection;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Linq;
using YAKEJI.Abp.Domain.Repositories;
using YAPACS.BusinessObjects.Exams;
using YAPACS.BusinessObjects.Managements.Appointments;
using YAPACS.BusinessObjects.Managements.Devices;
using YAPACS.BusinessObjects.Managements.Exams;
using YAPACS.BusinessObjects.Managements.ExpertGroups;
using YAPACS.Organizations;
using YAPACS.RisServer.Abstractions;
using YAPACS.RisServer.Interface.Imitate;
using YAPACS.RisServer.Services.Dtos;

using DeviceType = YAPACS.BusinessObjects.Managements.Devices.DeviceType;

namespace YAPACS.RisServer.Controllers;

[Authorize]
public class ExamDetailController(
                                     IMapper mapper,
                                     ICurrentUserOrganization currentUser,
                                     IRepository<ExamItem, Guid> examItemRepository,
                                     IRepository<ExamMatter, Guid> examMatterRep,
                                     IRepository<Exam, Guid> examRepository,
                                     IRepository<ExamMethod, Guid> examMethodRep,
                                     IRepository<ExamBodyParty, Guid> examBodyPartyRep,
                                     IRepository<AppointmentPlan, Guid> appointmentPlan,
                                     IRepository<AppointmentTimeInterval, Guid> appointmentTimeInterval,
                                     IRepository<ExamQueuing, Guid> examQueuingRep,
                                     IRepository<PatientMatter, Guid> patientMatterRep,
                                     IAsyncQueryableExecuter asyncQueryableExecuter,
                                     IExamNumberService numberService,
                                     IRepository<ExamCategory, Guid> categoryRep,
                                     IRepository<PatientFeature, Guid> patientFeature,
                                     IRepository<DeviceType, Guid> deviceTypeRep,
                                     IRepository<DepartmentExpertGroup, Guid> departmentExpertGroupRepository
                                 ) : AbpController
{

    private readonly IMapper _mapper = mapper;
    private readonly ICurrentUserOrganization _currentUser = currentUser;
    private readonly IRepository<ExamItem, Guid> _examItemRepository = examItemRepository;
    private readonly IAsyncQueryableExecuter _asyncQueryableExecuter = asyncQueryableExecuter;
    private readonly IRepository<ExamMatter, Guid> _examMatterRep = examMatterRep;
    private readonly IRepository<Exam, Guid> _examRepository = examRepository;
    private readonly IRepository<ExamMethod, Guid> _examMethodRep = examMethodRep;
    private readonly IRepository<ExamBodyParty, Guid> _examBodyPartyRep = examBodyPartyRep;
    private readonly IRepository<AppointmentPlan, Guid> _appointmentPlanRep = appointmentPlan;
    private readonly IRepository<AppointmentTimeInterval, Guid> _appointmentTimeIntervalRep = appointmentTimeInterval;
    private readonly IRepository<ExamQueuing, Guid> _examQueuingRepository = examQueuingRep;
    private readonly IRepository<PatientMatter, Guid> _patientMatterRep = patientMatterRep;
    private readonly IExamNumberService _examNumberService = numberService;
    private readonly IRepository<ExamCategory, Guid> _categoryRep = categoryRep;
    private readonly IRepository<PatientFeature, Guid> _patientFeature = patientFeature;
    private readonly IRepository<DeviceType, Guid> _deviceTypeRep = deviceTypeRep;
    private readonly IRepository<DepartmentExpertGroup, Guid> _departmentExpertGroupRepository = departmentExpertGroupRepository;

    /// <summary>
    /// (测试)获取amis schema
    /// </summary>
    /// <returns></returns>
    [HttpGet]
    [Route("api/exam-detail/getTestAmis")]
    public async Task<IActionResult> GetAdvanceSearchView()
    {
        AmisRes res = new();
        string content = string.Empty;
        Assembly assembly = Assembly.GetExecutingAssembly();
        string resourceName = $"{assembly.GetName().Name}.Resources.Test.FirstJson.json";
        using Stream stream = assembly.GetManifestResourceStream(resourceName);
        if (stream != null)
        {
            // 使用 StreamReader 读取资源内容
            using StreamReader reader = new(stream);
            content = await reader.ReadToEndAsync();
        }
        res.Data = new { amisJson = content };
        return Json(res);
    }


    #region 已选中检查项目Options
    [HttpGet]
    [Route("api/exam-detail/get-selected-items-options")]
    public async Task<IActionResult> GetSelectedItemsOptions(string deviceType, PatientSex sex)
    {
        var examItemQuery = await _examItemRepository.GetQueryableAsync();
        examItemQuery = examItemQuery.Where(e => e.Department.Oid == _currentUser.DepartmentId.Value && e.DeviceType.Oid.ToString() == deviceType);
        switch (sex)
        {
            case PatientSex.Male:
                examItemQuery = examItemQuery.Where(e => e.ApplicableSex == ApplicableSex.Male || e.ApplicableSex == ApplicableSex.None);
                break;
            case PatientSex.Female:
                examItemQuery = examItemQuery.Where(e => e.ApplicableSex == ApplicableSex.Female || e.ApplicableSex == ApplicableSex.None);
                break;
            case PatientSex.Other:
                examItemQuery = examItemQuery.Where(e => e.ApplicableSex == ApplicableSex.None);
                break;
            default:
                break;
        }
        var itemList = (await _asyncQueryableExecuter.ToListAsync(examItemQuery))
                       .Select(e => new { label = e.Name, value = e.Oid.ToString() });

        AmisRes res = new()
        {
            Data = new { options = itemList }
        };
        return Json(res);
    }
    #endregion


    #region 获取检查项目目录(dir)
    /// <summary>
    /// 获取所有的检查项目目录，并添加一个“未分组”目录
    /// </summary>
    /// <param name="deviceType"></param>
    /// <returns></returns>
    [HttpGet]
    [Route("api/exam-detail/get-exam-items-dir")]
    public async Task<IActionResult> GetExamItemsDir(string deviceType)
    {
        List<ExamItem> examItems = await _examItemRepository.GetListAsync(e => e.DeviceType.Oid.ToString() == deviceType
        && e.IsDirectory && e.IsActive && e.Department.Institution.Id==_currentUser.InstitutionId
        && e.Parent == null);
        var dirList = examItems.Select(e => new { e.Oid, e.Code, e.Name });
        List<object> list = [
            new
            {
                Oid="000",
                Code="000",
                Name="未分组"
            }
        ];
        list.AddRange(dirList.Select(e => new
        {
            e.Oid,
            e.Code,
            e.Name
        }));

        AmisRes res = new()
        {
            Data = new { items = list }
        };
        return Ok(res);
    }
    #endregion


    #region 根据目录获取检查项目
    /// <summary>
    /// 根据根目录获取
    /// </summary>
    /// <param name="dirOid"></param>
    /// <returns></returns>
    [HttpGet]
    [Route("api/exam-detail/get-exam-items-by-dir")]
    public async Task<IActionResult> GetExamItemsByDir(string dirOid, string deviceType, string sex, string method)
    {
        AmisRes res = new();
        // 使用性别
        List<int> applicableSexList = new List<int>();
        if (string.IsNullOrEmpty(sex))
        {
            applicableSexList.Add((int)ApplicableSex.Female);
            applicableSexList.Add((int)ApplicableSex.Male);
            applicableSexList.Add((int)ApplicableSex.None);
        }
        else
        {
            applicableSexList = FilteByPatientSex((PatientSex)Convert.ToInt32(sex));
        }


        ExamMethod examMethod = null;
        if (!string.IsNullOrEmpty(method))
        {
            examMethod = await _examMethodRep.GetAsync(Guid.Parse(method));
        }

        if (string.IsNullOrEmpty(dirOid) || dirOid == "000") // 未分组
        {
            var examItemQuery = await _examItemRepository.GetQueryableAsync();
            examItemQuery = examItemQuery.Where(e => e.Parent == null && e.DeviceType.Oid.ToString() == deviceType && !e.IsDirectory && applicableSexList.Contains((int)e.ApplicableSex));
            if (examMethod != null)
            {
                examItemQuery = examItemQuery.Where(e => e.ExamMethods.Contains(examMethod));
            }
            var examItemsList = await _asyncQueryableExecuter.ToListAsync(examItemQuery);
            var itemList = examItemsList.Select(e => new { oid = e.Oid.ToString(), code = e.Code, name = e.Name, selected = 0, isDir = e.IsDirectory });
            res.Data = new { rows = itemList };
        }
        else // 正常分组
        {
            var examItem = await _examItemRepository.GetAsync(Guid.Parse(dirOid));
            var children = await BuildTreeAsync(examItem, applicableSexList, examMethod);
            res.Data = new { rows = children };
            return Ok(res);
        }

        return Ok(res);
    }


    /// <summary>
    /// 性别过滤映射
    /// </summary>
    /// <param name="queryable"></param>
    /// <returns></returns>
    private List<int> FilteByPatientSex(PatientSex sex)
    {
        List<int> sexList = new List<int>();
        switch (sex)
        {
            case PatientSex.Male:
                sexList.Add((int)ApplicableSex.Male);
                sexList.Add((int)ApplicableSex.None);
                break;
            case PatientSex.Female:
                sexList.Add((int)ApplicableSex.Female);
                sexList.Add((int)ApplicableSex.None);
                break;
            case PatientSex.Other:
                sexList.Add((int)ApplicableSex.None);
                break;
            default:
                break;
        }
        return sexList;
    }

    // 递归构建树结构
    private async Task<List<object>> BuildTreeAsync(ExamItem examItem, List<int> applicableSexList, ExamMethod examMethod)
    {
        List<object> tree = [];
        var children = examItem.Children.Where(e => applicableSexList.Contains((int)e.ApplicableSex)); // 性别过滤
        if (examMethod != null)
        {
            children = children.Where(e => e.ExamMethods.Contains(examMethod)); // 如果存在检查方法，按检查方法过滤
        }
        foreach (var item in children)
        {
            List<object> childrenArray = [];
            if (item.Children.Count > 0)
            {
                childrenArray = await BuildTreeAsync(item, applicableSexList, examMethod);
            }
            tree.Add(new
            {
                item.Oid,
                item.Name,
                item.IsDirectory,
                item.Code,
                Children = childrenArray
            });
        }
        return tree;
    }
    #endregion


    #region 已选中检查部位Options
    /// <summary>
    /// 为显示已选中检查部位的Select组件获取下拉项用于显示
    /// </summary>
    /// <param name="deviceType"></param>
    /// <returns></returns>
    [HttpGet]
    [Route("api/exam-detail/get-selected-body-part-options")]
    public async Task<IActionResult> GetSelectedBodyPartOptions(string deviceType, PatientSex sex)
    {
        Guid departmenOid;
        if (_currentUser.DepartmentId != null)
            departmenOid = _currentUser.DepartmentId.Value;
        else
            departmenOid = Guid.Parse("014dc923-fffc-c43e-9838-3a12720e9275");  // 用于本地测试
        var bodyPartQuery = await _examBodyPartyRep.GetQueryableAsync();
        bodyPartQuery = bodyPartQuery.Where(e => e.DeviceType.Oid.ToString() == deviceType && e.Department.Oid == departmenOid);
        switch (sex)
        {
            case PatientSex.Male:
                bodyPartQuery = bodyPartQuery.Where(e => e.ApplicableSex == ApplicableSex.Male || e.ApplicableSex == ApplicableSex.None);
                break;
            case PatientSex.Female:
                bodyPartQuery = bodyPartQuery.Where(e => e.ApplicableSex == ApplicableSex.Female || e.ApplicableSex == ApplicableSex.None);
                break;
            case PatientSex.Other:
                bodyPartQuery = bodyPartQuery.Where(e => e.ApplicableSex == ApplicableSex.None);
                break;
            default:
                break;
        }
        var itemList = (await _asyncQueryableExecuter.ToListAsync(bodyPartQuery))
                       .Select(e => new { label = e.Name, value = e.Oid.ToString() });
        AmisRes res = new()
        {
            Data = new { options = itemList }
        };
        return Json(res);
    }
    #endregion


    #region 获取检查部位目录
    /// <summary>
    /// 获取当前设备类型下的检查部位目录
    /// </summary>
    /// <param name="deviceType"></param>
    /// <returns></returns>
    [HttpGet]
    [Route("api/exam-detail/get-body-part-dirs")]
    public async Task<IActionResult> GetBodyParyDirs(string deviceType)
    {
        List<ExamBodyParty> examBodyParties = await _examBodyPartyRep.GetListAsync(e =>
        e.IsDirectory && e.IsActive && e.Department.Institution.Id ==_currentUser.InstitutionId
        && e.DeviceType.Oid.ToString() == deviceType
        && e.Parent == null);
        var dirList = examBodyParties.Select(e => new
        {
            e.Oid,
            e.Code,
            e.Name
        });
        List<object> list = [
            new
            {
                Oid="000",
                Code="000",
                Name="未分组"
            }
        ];
        list.AddRange(dirList.Select(e => new
        {
            e.Oid,
            e.Code,
            e.Name
        }));
        AmisRes res = new()
        {
            Data = new { rows = list }
        };

        return Ok(res);
    }
    #endregion


    #region 根据目录获取检查部位
    [HttpGet]
    [Route("api/exam-detail/get-body-parties-by-dir")]
    public async Task<IActionResult> GetBodyPartiesByDir(string dirOid, string deviceType, string sex)
    {
        AmisRes res = new AmisRes();
        List<ExamBodyParty> list = new List<ExamBodyParty>();
        List<int> applicableSexList = new List<int>();
        if (string.IsNullOrEmpty(sex))
        {
            applicableSexList.Add((int)ApplicableSex.Female);
            applicableSexList.Add((int)ApplicableSex.Male);
            applicableSexList.Add((int)ApplicableSex.None);
        }
        else
        {
            applicableSexList = FilteByPatientSex((PatientSex)Convert.ToInt32(sex));// 适合性别
        }
        if (string.IsNullOrEmpty(dirOid) || dirOid == "000")  // 未分组
        {
            var bodyPatryQuery = await _examBodyPartyRep.GetQueryableAsync();
            bodyPatryQuery = bodyPatryQuery.Where(e => e.DeviceType.Oid.ToString() == deviceType && !e.IsDirectory && e.Department.Oid == _currentUser.DepartmentId);
            bodyPatryQuery = bodyPatryQuery.Where(e => e.Parent == null);
            bodyPatryQuery = bodyPatryQuery.Where(e => applicableSexList.Contains((int)e.ApplicableSex));
            var itemList = (await _asyncQueryableExecuter.ToListAsync(bodyPatryQuery))
                      .Select(e => new { oid = e.Oid.ToString(), code = e.Code, name = e.Name, selected = 0 });
            res.Data = new { rows = itemList };
        }
        else // 目录
        {
            var examBodyPartdir = await _examBodyPartyRep.GetAsync(Guid.Parse(dirOid));
            var children = await BuildBodyPartTreeAsync(examBodyPartdir, applicableSexList);
            res.Data = new { rows = children };
            return Ok(res);
        }
        return Ok(res);
    }


    // 递归获取子部位
    // 递归构建树结构
    private async Task<List<object>> BuildBodyPartTreeAsync(ExamBodyParty bodyPart, List<int> applicableSexList)
    {
        List<object> tree = [];
        foreach (var item in bodyPart.Children)
        {
            if (applicableSexList.Contains((int)item.ApplicableSex))
            {
                List<object> children = [];
                if (item.Children.Count > 0)
                {
                    children = await BuildBodyPartTreeAsync(item, applicableSexList);
                }
                tree.Add(new
                {
                    item.Oid,
                    item.Name,
                    item.IsDirectory,
                    item.Code,
                    Children = children
                });
            }
        }
        return tree;
    }
    #endregion


    #region 获取科室病人注意事项模板(用于下拉按钮)
    /// <summary>
    /// 获取科室注意事项列表
    /// </summary>
    /// <returns></returns>
    [HttpGet]
    [Route("api/exam-detail/get-exam-matters")]
    public async Task<IActionResult> GetExamMatters()
    {
        string departmentID;
        if (_currentUser.DepartmentId != null)
            departmentID = _currentUser.DepartmentId.ToString();
        else
            departmentID = "014dc923-fffc-c43e-9838-3a12720e9275";
        List<ExamMatter> list = await _examMatterRep.GetListAsync(e => e.Department.Oid == Guid.Parse(departmentID) && e.MatterType == ExamMatterType.Patient);
        var matterList = list.Select(e => new { oid = e.Oid, code = e.Code, content = e.Content, name = e.Name, isStrong = e.IsStrong });
        var data = new
        {
            buttons = matterList
        };
        return Json(new AmisRes { Status = 0, Msg = "succeed", Data = data });
    }
    #endregion


    #region 获取可选检查设备
    [HttpGet]
    [Route("api/exam-detail/get-device-options")]
    public async Task<IActionResult> GetDeviceOptions(Guid deviceType, Guid examId)
    {
        var startDate = Clock.Now.Date;
        var endDate = Clock.Now.Date.AddDays(1);

        var exam = await _examRepository.GetAsync(examId);
        var department = exam.Department;

        var devices = department.GetDevices().Where(d => d.DeviceType.Id == deviceType).ToList();

        var examQueuingList = (await _examQueuingRepository.GetQueryableAsync())
            .Where(q => q.Exam.Department.Oid == department.Oid)
            .Where(q => q.QueuingTime >= startDate && q.QueuingTime < endDate)
            .Where(q => q.Status == ExamQueuingStatus.Completed || q.Status == ExamQueuingStatus.Wait || q.Status == ExamQueuingStatus.Ready)
            .GroupBy(q => q.Device.Id, q => q.Status)
            .ToList();

        var result = devices.Select(d =>
        {
            var waitCount = examQueuingList
                 .Where(e => e.Key == d.Id)
                .SelectMany(e => e)
                .Where(e => e == ExamQueuingStatus.Wait || e == ExamQueuingStatus.Ready)
                .Count();

            var completedCount = examQueuingList
                .Where(e => e.Key == d.Id)
                .SelectMany(e => e)
                .Where(e => e == ExamQueuingStatus.Completed)
                .Count();

            return new
            {
                d.Oid,
                d.Name,
                Station = d.Station.Name,
                Room = d.Station.Room.Name,
                DeviceType = d.DeviceType.Oid,
                Selected = 0,
                WaitCount = waitCount,
                CompletedCount = completedCount,
                TotalCount = waitCount + completedCount
            };
        });

        AmisRes res = new()
        {
            Data = new
            {
                items = result
            }
        };
        return Json(res);
    }
    #endregion


    #region 检查设备下拉项
    [HttpGet]
    [Route("api/exam-detail/get-device-select-options")]
    public async Task<IActionResult> GetDeviceSelectOptions(Guid deviceType, Guid examId)
    {
        var res = new AmisRes();

        var startDate = Clock.Now.Date;
        var endDate = Clock.Now.Date.AddDays(1);

        var exam = await _examRepository.GetAsync(examId);
        var department = exam.Department;

        var devices = department.GetDevices().Where(d => d.DeviceType.Id == deviceType).ToList();

        var examQueuingList = (await _examQueuingRepository.GetQueryableAsync())
            .Where(q => q.Exam.Department.Oid == department.Oid )
            .Where(q => q.QueuingTime >= startDate && q.QueuingTime < endDate)
            .Where(q => q.Status == ExamQueuingStatus.Completed || q.Status == ExamQueuingStatus.Wait || q.Status == ExamQueuingStatus.Ready)
            .GroupBy(q => q.Device.Id, q => q.Status)
            .ToList();

        var data = devices.Select(d =>
        {
            var waitCount = examQueuingList
                .Where(e => e.Key == d.Id)
                .SelectMany(e => e)
                .Where(e => e == ExamQueuingStatus.Wait || e == ExamQueuingStatus.Ready)
                .Count();

            var completedCount = examQueuingList
                .Where(e => e.Key == d.Id)
                .SelectMany(e => e)
                .Where(e => e == ExamQueuingStatus.Completed)
                .Count();

            return new
            {
                Label = d.CompoundName,
                Value = d.Oid.ToString(),
                WaitCount = waitCount,
                CompletedCount = completedCount,
                TotalCount = waitCount + completedCount
            };
        });


        res.Data = data;
        res.Status = 0;
        return Ok(res);
    }
    #endregion


    #region 添加注意事项
    /// <summary>
    /// 添加注意事项
    /// </summary>
    /// <param name="patientMatter"></param>
    /// <returns></returns>
    [HttpGet]
    [Route("api/exam-detail/add-patient-matter")]
    public async Task<IActionResult> AddPatientMatter(string examOid, string content, bool isStrong)
    {
        AmisRes result = new AmisRes();
        try
        {
            // 检查是否存在
            Exam exam = await _examRepository.GetAsync(Guid.Parse(examOid));
            if (exam != null)
            {
                var patientMatter = await _patientMatterRep.NewEntityAsync();
                patientMatter.Content = content;
                patientMatter.IsStrong = isStrong;
                patientMatter.Exam = exam;
                result.Status = 0;
                result.Msg = "注意事项添加成功";
                result.Data = new
                {
                    oid = patientMatter.Oid,
                    isStrong = patientMatter.IsStrong,
                    content = patientMatter.Content,
                    order = patientMatter.Order
                };
            }
            else
            {
                result.Status = 2;
                result.Msg = "检查不存在";
                result.Data = "";
            }

        }
        catch (Exception ex)
        {
            result.Status = 1;
            result.Msg = ex.Message;
        }
        return Json(result);
    }
    #endregion


    #region 获取检查类别下拉项
    [HttpGet]
    [Route("api/exam-detail/get-exam-category-options")]
    public async Task<IActionResult> GetExamCategoryOptions(Guid deviceType, PatientSex sex, Guid examId)
    {
        AmisRes res = new AmisRes();
        Exam exam = await _examRepository.GetAsync(examId);
        var query = await _categoryRep.GetQueryableAsync();
        query = query.Where(e => e.DeviceType.Oid == deviceType && e.IsActive && e.Department == exam.Department);
        if (sex == PatientSex.Male)
        {
            query = query.Where(e => e.ApplicableSex != ApplicableSex.Female && e.IsActive);
        }
        else if (sex == PatientSex.Female)
        {
            query = query.Where(e => e.ApplicableSex != ApplicableSex.Male && e.IsActive);
        }
        var result = await _asyncQueryableExecuter.ToListAsync(query.OrderBy(e => e.Order).ThenBy(e => e.CreationTime).ThenBy(e => e.Name).Select(e => new
        {
            Label = e.Name,
            Value = e.Id
        }));
        res.Data = result;
        res.Status = 0;

        return Json(res);
    }
    #endregion


    #region 获取检方法下拉项目
    [HttpGet]
    [Route("api/exam-detail/get-exam-method-options")]
    public async Task<IActionResult> GetExamMethodOptions(Guid deviceType, ApplicableSex sex, Guid examId)
    {
        AmisRes res = new AmisRes();
        Exam exam = await _examRepository.GetAsync(examId);
        var queryable = await _examMethodRep.GetQueryableAsync();
        queryable = queryable.Where(e => e.DeviceType.Oid == deviceType && e.IsActive && e.Department.Oid == _currentUser.DepartmentId);
        var result = (await _asyncQueryableExecuter.ToListAsync(queryable)).OrderBy(e => e.Order).ThenBy(e => e.CreationTime).Select(e => new { label = e.Name, value = e.Oid.ToString() });
        res.Status = 0;
        res.Data = result;
        return Json(res);
    }
    #endregion


    #region 获取患者特征下拉项
    [HttpGet]
    [Route("api/exam-detail/get-patient-features-options")]
    public async Task<IActionResult> GetPatientFeaturesOptions(Guid examId)
    {
        Exam exam = await _examRepository.GetAsync(examId);
        var query = (await _patientFeature.GetListAsync(e => e.IsActive && e.Department == exam.Department)).OrderBy(e => e.Order).ThenBy(e => e.CreationTime).Select(e => new { label = e.Name, value = e.Oid });
        AmisRes res = new AmisRes();
        res.Status = 0;
        res.Data = query;

        return Json(res);
    }
    #endregion


    #region 获取设备类型下拉
    [HttpGet]
    [Route("api/exam-detail/get-device-type-options")]
    public async Task<IActionResult> GetDeviceTypeOptions()
    {
        var result = (await _deviceTypeRep.GetListAsync(e => e.IsActive)).OrderBy(e => e.Order).Select(e => new { label = e.Name, value = e.Oid });
        AmisRes res = new AmisRes();
        res.Status = 0;
        res.Data = result;
        return Json(res);
    }
    #endregion


    #region  患者注意事项修改
    [HttpGet]
    [Route("api/exam-detail/update-patient-matter")]
    public async Task<IActionResult> UpdatePatientMatter(string oid, string content, bool isStrong)
    {
        AmisRes res = new AmisRes();
        try
        {
            var patientMatter = await _patientMatterRep.GetAsync(Guid.Parse(oid));
            if (patientMatter != null)
            {
                patientMatter.Content = content;
                patientMatter.IsStrong = isStrong;
                List<PatientMatter> list = await _patientMatterRep.GetListAsync(e => e.Exam.Oid == patientMatter.Exam.Oid);
                var data = list.Select(e => new { oid = e.Oid, content = e.Content, isStrong = e.IsStrong });
                res.Data = data;
            }
            else
            {
                res.Status = 1;// 注意事项不存在
                res.Msg = "注意事项不存在";
            }
        }
        catch (Exception ex)
        {
            res.Status = 2;
            res.Msg = ex.Message;
        }
        return Json(res);
    }
    #endregion


    #region 删除注意事项
    /// <summary>
    /// 删除注意事项
    /// </summary>
    /// <param name="oid"></param>
    /// <returns></returns>
    [HttpGet]
    [Route("api/exam-detail/delete-patient-matter")]
    public async Task<IActionResult> DeletePatientMatter(string oid, string examOid)
    {
        AmisRes res = new AmisRes();
        if (!string.IsNullOrEmpty(oid) && !string.IsNullOrEmpty(examOid))
        {
            try
            {
                var patientMatter = await _patientMatterRep.GetAsync(Guid.Parse(oid));
                Exam exam = await _examRepository.GetAsync(Guid.Parse(examOid));
                exam.PatientMatters.Remove(patientMatter);
                await _patientMatterRep.DeleteAsync(patientMatter.Oid);
                var data = exam.PatientMatters.ToList().Select(e => new { oid = e.Oid.ToString(), content = e.Content, order = e.Order, isStrong = e.IsStrong });

                res.Data = new
                {
                    matters = data
                };
            }
            catch (Exception ex)
            {
                res.Status = 3;
                res.Msg = ex.Message;
            }
        }
        else
        {
            res.Status = 1;
            res.Msg = "请求错误，未传出患者注意事项的oid";
        }

        return Json(res);
    }
    #endregion


    #region 计算检查方法、检查部位、患者注意事项
    [HttpPost]
    [Route("api/exam-detail/calculate-parties-methods")]
    public async Task<IActionResult> CalculatePartieMethods([FromBody] ExamItemCalculateDto examItemCalculateDto)
    {
        ApiActionRes res = new ApiActionRes();
        List<ItemDto> bodyPartyList = new List<ItemDto>();
        // 用于收集模板
        List<MatterDto> examMatters = new List<MatterDto>();
        // 用于响应
        List<MatterDto> patientMatterLsit = new List<MatterDto>();
        // 用户实体类存储
        List<PatientMatter> matters = new List<PatientMatter>();

        Guid oid = examItemCalculateDto.examOid;
        Exam exam = await _examRepository.GetAsync(oid);


        foreach (ItemDto item in examItemCalculateDto.examItemList)
        {
            ExamItem examItem = await _examItemRepository.GetAsync(Guid.Parse(item.Oid.ToString()));

            // 计算检查项目应有的检查部位
            foreach (ExamBodyParty examBodyParty in examItem.ExamBodyParties)
            {
                ItemDto itemDto = new ItemDto();
                itemDto.Name = examBodyParty.Name;
                itemDto.Code = examBodyParty.Code;
                itemDto.Oid = examBodyParty.Oid.ToString();
                itemDto.Selected = 1;
                bodyPartyList.Add(itemDto);
            }

            // 计算注意事项
            foreach (ExamMatter matter in examItem.ExamMatters)
            {
                if (matter.MatterType == 0)
                {
                    MatterDto matterTemplate = new MatterDto();
                    matterTemplate.Oid = matter.Oid.ToString();
                    matterTemplate.Name = matter.Name;
                    matterTemplate.Content = matter.Content;
                    matterTemplate.IsStrong = matter.IsStrong;
                    // 模板收集
                    examMatters.Add(matterTemplate);
                }
            }
        }
        // 模板去重
        examMatters = examMatters.GroupBy(e => e.Oid).Select(group => new MatterDto
        {
            Oid = group.Key.ToString(),
            Name = group.First().Name,
            Content = group.First().Content,
            IsStrong = group.First().IsStrong
        })
                                            .ToList();
        // 与前端已选中注意事项合并去重
        examMatters = examMatters.Concat(examItemCalculateDto.patientMatters)
                                 .GroupBy(e => new { e.Content, e.IsStrong })
                                 .Select(group => new MatterDto { Oid = group.First().Oid.ToString(), Content = group.Key.Content.ToString(), IsStrong = group.Key.IsStrong })
                                 .ToList();
        // 清空exam.PatientMatters
        exam.PatientMatters.RemoveAll(exam => 1 == 1);
        // 根据模板添加exam的PatientMatters
        foreach (var item in examMatters)
        {
            PatientMatter patientMatter = await _patientMatterRep.NewEntityAsync();
            patientMatter.Content = item.Content;
            patientMatter.IsStrong = item.IsStrong;
            exam.PatientMatters.Add(patientMatter);
        }

        // 获取返回对象
        foreach (var item in exam.PatientMatters)
        {
            MatterDto matterDto = new MatterDto();
            matterDto.Oid = item.Oid.ToString();
            matterDto.Content = item.Content;
            matterDto.IsStrong = item.IsStrong;
            patientMatterLsit.Add(matterDto);
        }

        // 检查部位去重
        bodyPartyList = bodyPartyList.Concat(examItemCalculateDto.examBodyParties)
                                     .GroupBy(e => e.Oid)
                                     .Select(group => new ItemDto { Oid = group.Key.ToString(), Code = group.First().Code, Name = group.First().Name, Selected = 1 })
                                     .ToList();

        res.responseStatus = 0;
        res.responseMsg = "success";
        res.responseData = new
        {
            BodyPartyList = bodyPartyList,
            PatientMatterList = patientMatterLsit
        };

        return Json(res);
    }
    #endregion


    #region 获取预约配置
    /// <summary>
    /// 获取预约配置
    /// </summary>
    /// <param name="examOid">检查Oid</param>
    /// <param name="deviceOid">选定设备,可为空</param>
    /// <param name="selectedDate">选定日期</param>
    /// <returns></returns>
    [HttpGet]
    [Route("api/exam-detail/get-appointment-data")]
    public async Task<IActionResult> GetAppointmentData(string examOid, string deviceOids, DateTime selectedDate)
    {

        AmisRes res = new AmisRes();
        List<object> columns = [];
        List<object> rows = [];
        try
        {
            if (!string.IsNullOrEmpty(examOid))
            {
                Exam exam = await _examRepository.GetAsync(Guid.Parse(examOid));
                // 当前预约计划  (决定当前选中单元格)
                AppointmentPlan currentPlan = exam.AppointmentPlan;

                // 设备列表(决定显示行数)
                var deviceList = exam.Department.GetDevices().Where(d => d.DeviceType == exam.DeviceType).ToList();

                if (!string.IsNullOrEmpty(deviceOids))
                {
                    var deviceIds = deviceOids.Split(',');
                    deviceList = deviceList.Where(d => deviceIds.Contains(d.Oid.ToString())).ToList();
                }

                // 预约时段 (根据设备类型) 决定行数
                List<AppointmentTimeInterval> timeIntervalList = await _appointmentTimeIntervalRep.GetListAsync(e => e.DeviceType == exam.DeviceType);
                timeIntervalList = timeIntervalList.OrderBy(e => e.Order).ToList();
                List<AppointmentPlan> planList = await _appointmentPlanRep.GetListAsync(e => e.Date == selectedDate && timeIntervalList.Contains(e.TimeInterval) && deviceList.Contains(e.Device));

                deviceList = deviceList.OrderBy(d => d.Station.Room.Order).ThenBy(d => d.CreationTime).ToList();

                // 构建定义列数据  columns
                foreach (var device in deviceList)
                {
                    columns.Add(new
                    {
                        device.Oid,
                        DeviceName = device.CompoundName
                    });
                }

                // 构建表格数据 rows
                foreach (var interval in timeIntervalList)
                {
                    // 构建行
                    List<object> row = [];
                    // 添加第一个单元格，显示时间段信息
                    row.Add(new
                    {
                        TimeIntervalOid = interval.Oid,
                        InteralName = interval.StartTime.Value.ToString("hh\\:mm") + "-" + interval.EndTime.Value.ToString("hh\\:mm")
                    });
                    foreach (var device in deviceList)
                    {
                        // 根据时间段和设备获取计划
                        object cell = null;
                        if (planList.Exists(e => e.Device == device && e.TimeInterval == interval))
                        {
                            AppointmentPlan plan = planList.First(e => e.Device == device && e.TimeInterval == interval);
                            cell = new
                            {
                                Id = plan.Oid,
                                plan.CurrentCount,
                                plan.MaxCount,
                                DeviceOid = device.Oid,
                                DeviceName = device.Name,
                                Interval = interval.Name
                            };
                        }
                        else // 没有计划
                        {
                            cell = new
                            {
                                Id = "",
                                CurrentCount = 0,
                                MaxCount = 0,
                                DeviceOid = device.Oid,
                                DeviceName = device.Name,
                                Interval = interval.Name
                            };
                        }
                        row.Add(cell);
                    }
                    rows.Add(row);// 添加行
                }

                res.Data = new
                {
                    Rows = rows,
                    Columns = columns,
                    CurrentPlan = currentPlan == null ? "" : currentPlan.Oid.ToString()
                };
            }
            else
            {
                res.Status = 1;
                res.Msg = "检查Oid参数为空";
            }
        }
        catch (Exception ex)
        {
            res.Status = 2;
            res.Msg = ex.Message;
        }
        return Ok(res);
    }
    #endregion


    #region 保存预约
    /// <summary>
    /// 预约保存
    /// </summary>
    /// <param name="examOid"></param>
    /// <param name="appointmentPlanId"></param>
    /// <param name="examCategoryOid"></param>
    /// <param name="deviceOid"></param>
    /// <returns></returns>
    [HttpGet]
    [Route("api/exam-detail/save-appointment")]
    public async Task<IActionResult> SaveAppointment(string examOid, string planOid, string deviceName, string deviceOid)
    {
        // 修改和新增预约，只需要操作Exam.AppointmentPlan就行
        AmisRes res = new AmisRes();
        try
        {
            Exam exam = await _examRepository.GetAsync(Guid.Parse(examOid));
            ExamDto examDto = null;
            // 获取新预约计划
            AppointmentPlan currentPlan = null;
            if (!string.IsNullOrEmpty(planOid) && exam.AppointmentPlan != null) // 有老预约计划
            {
                if (planOid != exam.AppointmentPlan.Oid.ToString()) // 新老预约计划不同
                {
                    currentPlan = await _appointmentPlanRep.GetAsync(Guid.Parse(planOid));
                    exam.ExamDevice = currentPlan.Device;
                    exam.AppointmentPlan = currentPlan;  //此处会更新预约编号
                    await _examNumberService.SetAppointmentNumberAsync(exam);
                    // 老计划有队列，新预约在今天
                    if (exam.ExamQueuing != null && currentPlan.Date == Clock.Now.Date)
                    {
                        int hours = exam.AppointmentPlan.TimeInterval.StartTime.Value.Hours;
                        if (hours < 12)
                        {
                            exam.ExamQueuing.StartTime = Clock.Now.Date; // 当天凌晨零点开始
                        }
                        else
                        {
                            exam.ExamQueuing.StartTime = Clock.Now.Date.AddHours(13).AddMinutes(0).AddSeconds(0);
                        }
                    }
                    else if (exam.ExamQueuing != null && currentPlan.Date != Clock.Now.Date) // 新的预约不在今天
                    {
                        await _examQueuingRepository.DeleteAsync(exam.ExamQueuing.Oid);
                        exam.ExamQueuing = null; // 删除队列对象
                    }

                    examDto = _mapper.Map<ExamDto>(exam);
                    res.Msg = "预约计划保存成功！";
                    res.Data = new
                    {
                        appointmentNumber = exam.ExamAppointment.AppointmentNumber,
                        appointmentName = examDto.AppointmentName,
                        appointmemtDeviceOid = currentPlan.Device.Oid.ToString(),
                        appointmentDeviceName = currentPlan.Device.CompoundName,
                        appointmentDate = currentPlan.Date.Value.ToString("yyyy-MM-dd")
                    };
                }
                else // 预约计划重复
                {
                    res.Status = 1;
                    res.Msg = "请选择与当前预约计划不同的预约计划，再提交！";
                }
            }
            else if (!string.IsNullOrEmpty(planOid) && exam.AppointmentPlan == null) // 本来没有预约计划
            {
                currentPlan = await _appointmentPlanRep.GetAsync(Guid.Parse(planOid));
                exam.ExamDevice = currentPlan.Device;
                exam.AppointmentPlan = currentPlan;
                await _examNumberService.SetAppointmentNumberAsync(exam);
                examDto = _mapper.Map<ExamDto>(exam);
                res.Msg = "预约计划保存成功！";
                res.Data = new
                {
                    appointmentNumber = exam.ExamAppointment.AppointmentNumber,
                    appointmentName = examDto.AppointmentName,
                    appointmemtDeviceOid = currentPlan.Device.Oid.ToString(),
                    appointmentDeviceName = currentPlan.Device.CompoundName,
                    appointmentDate = currentPlan.Date.Value.ToString("yyyy-MM-dd")
                };
            }
            else if (string.IsNullOrEmpty(planOid) && exam.AppointmentPlan != null) // 取消预约
            {
                exam.AppointmentPlan = null;  // 清空预约计划
                if (exam.ExamQueuing != null)
                {
                    await _examQueuingRepository.DeleteAsync(exam.ExamQueuing.Oid);
                    exam.ExamQueuing = null;  // 删除队列
                }
                examDto = _mapper.Map<ExamDto>(exam);
                res.Msg = "取消预约成功！";
                res.Data = new
                {
                    appointmentNumber = "",
                    appointmentName = "",
                    appointmentDate = Clock.Now.ToString("yyyy-MM-dd"),
                    appointmemtDeviceOid = deviceOid,
                    appointmentDeviceName = deviceName,
                };
            }
        }
        catch (Exception ex)
        {
            await UnitOfWorkManager.Current.RollbackAsync();
            res.Data = null;
            res.Msg = ex.Message;
            res.Status = 1;
        }
        return Json(res);
    }
    #endregion


    #region 生成预约编号
    [HttpGet]
    [Route("api/set-appointment-number")]
    public async Task<IActionResult> SetAppointmentNumber(Guid examId, string planOid)
    {
        AmisRes res = new AmisRes();
        Exam exam = await _examRepository.GetAsync(examId);
        if (!string.IsNullOrEmpty(planOid))
        {
            res.Data = new
            {
                appointmentNumer = await _examNumberService.SetAppointmentNumberAsync(exam)
            };
        }
        else
        {
            res.Data = new
            {
                appointmentNumer = ""
            };
        }
        return Ok(res);
    }
    #endregion


    #region  (预约计划弹出框)获取预约设备下拉项
    [HttpGet]
    [Route("api/exam-detail/get-devices-options")]
    public async Task<IActionResult> GetDeviceOptions(Guid examOid)
    {
        var exam = await _examRepository.GetAsync(examOid);
        var devices = exam.Department.GetDevices()
            .Where(d => d.DeviceType == exam.DeviceType)
            .Select(e => new
            {
                label = e.CompoundName,
                value = e.Oid.ToString()
            });
        var data = new
        {
            options = devices
        };
        return Json(new AmisRes { Data = data });
    }
    #endregion


    #region 获取专家组下拉项
    [HttpGet]
    [Route("api/exam-detail/get-department-expert-group-options")]
    public async Task<IActionResult> GetDepartmentExpertGroupOptins()
    {
        AmisRes res = new AmisRes();
        var query = await _departmentExpertGroupRepository.GetQueryableAsync();
        query = query.Where(e => e.Department.Oid == _currentUser.DepartmentId && e.ExpertGroup.IsActive).OrderBy(e => e.ExpertGroup.Order).ThenBy(e => e.ExpertGroup.Name);
        var list = (await _asyncQueryableExecuter.ToListAsync(query)).Select(e => new { label = e.ExpertGroup.Name, value = e.ExpertGroup.Oid.ToString() });
        res.Data = list;
        return Json(res);
    }
    #endregion

}
